#pragma once

#include "proxy/common/factory.h"
#include "config.h"
#include <unordered_map>


struct Server;
struct Router;

struct Tunnel : public Obj {

  Tunnel (Server* server, Router* router, jlib::RSA& rsa, s32 socket, u32 ipv4, u16 port);
  ~Tunnel () override;

  void startup ();
  void shutdown ();

  void upLoop ();
  void downLoop ();

  bool handshake ();
  void write (Ptr<IpPackage> pkg);


public:
  List joint;

private:
  Server* _server;
  Router* _router;
  jlib::RSA& _rsa;
  s32 _socket;
  u32 _ipv4;
  u16 _port;

  std::thread* _upWorker {nullptr};
  std::thread* _downWorker {nullptr};

  jlib::AES _aes;
  u8 _aes_key[32];

  BlockQueue<IpPackage, &IpPackage::joint> _queue;
  std::mutex _cache_mutex;
  ByteBuffer<> _cache {IpPackage::MAX_SIZE + 16};
  std::mutex _close_mutex;
  volatile bool _closed {false};
};
